package TDAPila;

import java.util.Vector;

/**
 * Pila implementada con un arreglo
 * @author Jordan
 *
 * @param <T>
 */
public class ArrayStack<T> implements Stack<T>{
	
	private int size;
	private T[] pila;
//CONSTRUCTORES
	/**
	 * constructor que le pasas la cantidad de celdas que va a tener maximo el arreglo
	 * @param celdas
	 */
	@SuppressWarnings("unchecked")
	public ArrayStack(int celdas){
		pila=(T[])new Object[celdas]; 
		size=0;
	}
	
	/**
	 * constructor por defecto en 8 celdas
	 */
	public ArrayStack() {
		pila=(T[])new Object[8];
		size=0;
	}
//-------------------------------------------------------------
	/**
	 * @override 
	 */
	public int size() {
		return size;
	}
//-------------------------------------------------------------

	/**
	 * @override 
	 */
	public boolean isEmpty(){
		return size()==0;
	}
//-------------------------------------------------------------
	/**
	 * @override 
	 */
	public T top() throws EmptyStackException {
		if (isEmpty()) 
			throw new EmptyStackException("la pila:: top()");
		return pila[size-1];
	}
//-------------------------------------------------------------
	/**
	 * @override 
	 */
	public void push(T t) {
		if(isFull())
			reorganizarPila();
		pila[size]=t;
		size++;
	}
//-------------------------------------------------------------
	/**
	 * @override 
	 */
	public T pop() throws EmptyStackException {
		if (isEmpty())
			throw new EmptyStackException("la pila:: pop()");
		T res=pila[size-1];
		pila[size-1]=null;
		size--;
		return res;
	}
//-------------------------------------------------------------
	private void reorganizarPila() {
		T[] pilaAux=(T[])new Object[pila.length*2]; 
		int index=0;
		for(T t:pila){
			pilaAux[index]=t;
			index++;
		}
		pila=pilaAux;
	}
//-------------------------------------------------------------	
	/**
	 * @return retorna TRUE si la pila esta llena en caso contrario retorna FALSE.
	 */
	private boolean isFull() {
		return size==pila.length;
	}
//-------------------------------------------------------------
	/**retorna un String con la cantidad de elemento en la la pila
	 * @return retorna un String con la cantidad de elemento en la la pila.
	 */
	private String mostrar() {
		if (isEmpty()) return "No hay elementos en la Cola.";
		String s="Elementos de la cola enumerados desde el tope: ";
		ArrayStack<T> aux1=new ArrayStack<T>();
		T aux;
		//Desapilo y enumero en el String O(n)
		while(!isEmpty()){
			try {
				aux=pop();
				s=s+aux+" ";
				aux1.push(aux);
			} catch (EmptyStackException e) {}
		}
		//Apilo nuevamente O(n)
		while(!aux1.isEmpty())
			try {
				push(aux1.pop());
			} 
			catch (EmptyStackException e) {}
		return s;
	}
//-------------------------------------------------------------	
	/**
	 * @param t elemento que se inserta en la pila que llama al metodo.
	 * @return retorna un string con el elemento que se acaba de insertar en la pila
	 */
	@Deprecated
	protected String insertar(T t) {
	push(t);
	return "Se inserto el elemento "+t;
	}
//-------------------------------------------------------------	
	/**
	 * retorna un string mostrando el elemento buscado.
	 * @return retorna un string mostrando el elemento buscado. 
	 */
	private String buscarSegunCriterio(){
		T aux;
		try {	aux = top();
				return "En el el tope de la pila se encuentra el elemento "+aux;
		}
		catch (EmptyStackException e) {return e.getMessage();}		
	}
//-------------------------------------------------------------
	/**
	 * @return retorna un string mostrando el elemento removido. 
	 */
	@Deprecated
	private String removerSegunCriterio() {
	try {return "Se removio segun el criterio de Pila a "+pop();
		} catch (EmptyStackException e) {return e.getMessage();}
	}
//-------------------------------------------------------------	
	/**
	 * OPERACIONES EXTRAS: ----> INVERTIR O(n)
	*/
	public void invertir(){
		ArrayStack<T> p1,p2;
		p1=new ArrayStack<T>();
		p2=new ArrayStack<T>();
		while(!this.isEmpty())
			try {p1.push(this.pop());} catch (EmptyStackException e) {} //O(n)
		while(!p1.isEmpty())
			try {p2.push(p1.pop());} catch (EmptyStackException e) {} //O(n)
		while(!p2.isEmpty())
			try {this.push(p2.pop());} catch (EmptyStackException e) {} //O(n)
			
	}
//-------------------------------------------------------------
}
